import { Provide, Inject } from '@midwayjs/core';
import axios from 'axios';
import { DatabaseService } from './database.service';
import * as fs from 'fs';
import * as path from 'path';

/**
 * 翻译服务类
 * 负责调用dmxapi进行翻译，并处理缓存逻辑
 */
@Provide()
export class TranslateService {
  @Inject()
  databaseService: DatabaseService;

  // dmxapi配置
  private readonly apiConfig = {
    url: 'https://www.dmxapi.cn/v1/chat/completions',
    headers: {
      'Authorization': 'Bearer sk-834gcXipdT1A0OWbJWGDtMQMuuqENTNhGUbenwENstQF7rpb',
      'Content-Type': 'application/json'
    }
  };

  /**
   * 翻译单词，支持缓存
   * @param word 要翻译的单词
   * @returns 翻译结果
   */
  async translateWord(word: string): Promise<string> {
    // 先检查缓存
    const cachedResult = await this.databaseService.getWordTranslation(word);
    if (cachedResult) {
      return cachedResult;
    }

    // 缓存中没有，调用API
    const translation = await this.callDmxApi(word);
    
    // 保存到缓存
    await this.databaseService.saveWordTranslation(word, translation);
    
    return translation;
  }

  /**
   * 调用dmxapi获取词汇分析
   * @param word 要分析的单词
   * @returns API响应内容
   */
  private async callDmxApi(word: string): Promise<string> {
    const requestData = {
      max_tokens: 8192,
      model: "gemini-2.0-flash",
      temperature: 0.8,
      top_p: 1,
      presence_penalty: 1,
      messages: [
        {
          role: "system",
          content: "你是一个英语老师"
        },
        {
          role: "user",
          content: `词汇是${word}，先翻译这个词的中国宏文意思，请列举他的词根，这些词根例句+中文翻译`
        }
      ]
    };

    try {
      const response = await axios.post(
        this.apiConfig.url,
        requestData,
        { 
          headers: this.apiConfig.headers,
          timeout: 30000 // 30秒超时
        }
      );

      if (response.data && response.data.choices && response.data.choices[0]) {
        return response.data.choices[0].message.content;
      } else {
        throw new Error('API响应格式不正确');
      }
    } catch (error) {
      console.error('调用dmxapi失败:', error);
      
      // 返回一个友好的错误信息
      if (error.code === 'ECONNABORTED') {
        return `词汇 "${word}" 的分析请求超时，请稍后重试。`;
      } else if (error.response) {
        return `词汇 "${word}" 的分析服务暂时不可用，错误代码: ${error.response.status}`;
      } else {
        return `词汇 "${word}" 的分析暂时无法获取，请检查网络连接。`;
      }
    }
  }

  /**
   * 翻译句子，支持缓存，并预缓存句子中的所有单词
   * @param sentence 要翻译的句子
   * @returns 翻译结果
   */
  async translateSentence(sentence: string): Promise<string> {
    // 先检查缓存
    const cachedResult = await this.databaseService.getWordTranslation(sentence);
    if (cachedResult) {
      // 即使句子已缓存，也要预缓存单词（异步执行，不阻塞响应）
      this.preCacheWordsFromSentence(sentence);
      return cachedResult;
    }

    // 执行句子翻译
    const translation = await this.callDmxApiForSentence(sentence);
    
    // 保存句子翻译到缓存
    await this.databaseService.saveWordTranslation(sentence, translation);
    
    // 异步预缓存单词（不阻塞响应）
    this.preCacheWordsFromSentence(sentence).catch(error => {
      console.error('异步预缓存单词失败:', error);
    });
    
    return translation;
  }

  /**
   * 从句子中提取单词并预缓存
   * @param sentence 要处理的句子
   */
  private async preCacheWordsFromSentence(sentence: string): Promise<void> {
    try {
      // 提取句子中的单词
      const words = this.extractWordsFromSentence(sentence);
      
      if (words.length > 0) {
        // 过滤出未缓存的单词
        const uncachedWords = [];
        for (const word of words) {
          const cached = await this.databaseService.getWordTranslation(word);
          if (!cached) {
            uncachedWords.push(word);
          }
        }
        
        // 批量翻译未缓存的单词
        if (uncachedWords.length > 0) {
          console.log(`预缓存 ${uncachedWords.length} 个单词:`, uncachedWords);
          await this.translateWords(uncachedWords);
        }
      }
    } catch (error) {
      console.error('预缓存单词失败:', error);
      // 预缓存失败不影响主流程，只记录错误
    }
  }

  /**
   * 从句子中提取单词，去除空格和特殊符号
   * @param sentence 要处理的句子
   * @returns 单词数组
   */
  private extractWordsFromSentence(sentence: string): string[] {
    if (!sentence || typeof sentence !== 'string') {
      return [];
    }

    // 使用正则表达式提取单词，只保留字母
    const words = sentence
      .toLowerCase() // 转为小写
      .match(/[a-zA-Z]+/g) || []; // 提取所有字母组成的单词
    
    // 去重并过滤掉过短的单词（如 a, I 等）
    const uniqueWords = [...new Set(words)]
      .filter(word => word.length >= 2); // 只保留长度>=2的单词
    
    return uniqueWords;
  }

  /**
   * 调用dmxapi进行句子翻译
   * @param sentence 要翻译的句子
   * @returns API响应内容
   */
  private async callDmxApiForSentence(sentence: string): Promise<string> {
    const requestData = {
      max_tokens: 8192,
      model: "gemini-2.0-flash",
      temperature: 0.8,
      top_p: 1,
      presence_penalty: 1,
      messages: [
        {
          role: "system",
          content: "你是一个英语老师"
        },
        {
          role: "user",
          content: `请将以下英文翻译成中文：${sentence}`
        }
      ]
    };

    try {
      const response = await axios.post(
        this.apiConfig.url,
        requestData,
        { 
          headers: this.apiConfig.headers,
          timeout: 30000 // 30秒超时
        }
      );

      if (response.data && response.data.choices && response.data.choices[0]) {
        return response.data.choices[0].message.content;
      } else {
        throw new Error('API响应格式不正确');
      }
    } catch (error) {
      console.error('调用dmxapi进行句子翻译失败:', error);
      
      // 返回一个友好的错误信息
      if (error.code === 'ECONNABORTED') {
        return `句子翻译请求超时，请稍后重试。`;
      } else if (error.response) {
        return `句子翻译服务暂时不可用，错误代码: ${error.response.status}`;
      } else {
        return `句子翻译暂时无法获取，请检查网络连接。`;
      }
    }
  }

  /**
   * 批量翻译多个单词，每秒只请求一次接口
   * @param words 单词数组
   * @returns 翻译结果数组
   */
  async translateWords(words: string[]): Promise<{ word: string; translation: string }[]> {
    const results = [];
    
    for (let i = 0; i < words.length; i++) {
      const word = words[i];
      
      try {
        // 记录开始时间
        const startTime = Date.now();
        
        // 翻译单词
        const translation = await this.translateWord(word);
        results.push({ word, translation });
        
        // 计算已用时间
        const elapsedTime = Date.now() - startTime;
        
        // 如果不是最后一个单词，且用时少于1秒，则等待剩余时间
        if (i < words.length - 1 && elapsedTime < 1000) {
          const waitTime = 1000 - elapsedTime;
          console.log(`翻译单词 "${word}" 完成，等待 ${waitTime}ms 后处理下一个单词`);
          await this.delay(waitTime);
        } else {
          console.log(`翻译单词 "${word}" 完成，用时 ${elapsedTime}ms`);
        }
        
      } catch (error) {
        console.error(`翻译单词 "${word}" 失败:`, error);
        results.push({ 
          word, 
          translation: `翻译失败: ${error.message}` 
        });
        
        // 即使失败也要等待，保持请求频率限制
        if (i < words.length - 1) {
          console.log(`翻译单词 "${word}" 失败，等待 1000ms 后处理下一个单词`);
          await this.delay(1000);
        }
      }
    }
    
    return results;
  }

  /**
   * 延迟函数
   * @param ms 延迟毫秒数
   */
  private delay(ms: number): Promise<void> {
    return new Promise(resolve => setTimeout(resolve, ms));
  }

  /**
   * 解析句子中的词组，支持缓存
   * @param sentence 要解析的句子
   * @returns 词组解析结果
   */
  async analyzePhrases(sentence: string): Promise<string> {
    // 生成缓存键，使用特殊前缀区分词组解析
    const cacheKey = `phrases_${sentence}`;
    
    // 先检查缓存
    const cachedResult = await this.databaseService.getWordTranslation(cacheKey);
    if (cachedResult) {
      return cachedResult;
    }

    // 缓存中没有，调用API
    const analysis = await this.callDmxApiForPhrases(sentence);
    
    // 保存到缓存
    await this.databaseService.saveWordTranslation(cacheKey, analysis);
    
    return analysis;
  }

  /**
   * 调用dmxapi进行词组解析
   * @param sentence 要解析的句子
   * @returns API响应内容
   */
  private async callDmxApiForPhrases(sentence: string): Promise<string> {
    const requestData = {
      max_tokens: 8192,
      model: "gemini-2.0-flash",
      temperature: 0.8,
      top_p: 1,
      presence_penalty: 1,
      messages: [
        {
          role: "system",
          content: "你是一个英语老师，专门分析英语句子中的词组和短语"
        },
        {
          role: "user",
          content: `请分析以下英语句子中的常见词组和短语，并提供详细解释：

句子：${sentence}

请按以下格式输出：
1. 词组名称 - 中文含义
   例句：英文例句
   翻译：中文翻译

2. 词组名称 - 中文含义
   例句：英文例句
   翻译：中文翻译

请重点关注：
- 动词短语 (phrasal verbs)
- 介词短语 (prepositional phrases)  
- 固定搭配 (collocations)
- 习语表达 (idiomatic expressions)`
        }
      ]
    };

    try {
      const response = await axios.post(
        this.apiConfig.url,
        requestData,
        { 
          headers: this.apiConfig.headers,
          timeout: 30000 // 30秒超时
        }
      );

      if (response.data && response.data.choices && response.data.choices[0]) {
        return response.data.choices[0].message.content;
      } else {
        throw new Error('API响应格式不正确');
      }
    } catch (error) {
      console.error('调用dmxapi进行词组解析失败:', error);
      
      // 返回一个友好的错误信息
      if (error.code === 'ECONNABORTED') {
        return `词组解析请求超时，请稍后重试。`;
      } else if (error.response) {
        return `词组解析服务暂时不可用，错误代码: ${error.response.status}`;
      } else {
        return `词组解析暂时无法获取，请检查网络连接。`;
      }
    }
  }

  /**
   * 获取文本标题，将内容总结为10个字
   * @param content 要总结的内容
   * @returns 10个字的标题
   */
  async getTitle(content: string): Promise<string> {
    // 先检查缓存
    const cacheKey = `title_${content}`;
    const cachedResult = await this.databaseService.getWordTranslation(cacheKey);
    if (cachedResult) {
      return cachedResult;
    }

    // 缓存中没有，调用API
    const title = await this.callDmxApiForTitle(content);
    
    // 保存到缓存
    await this.databaseService.saveWordTranslation(cacheKey, title);
    
    return title;
  }

  /**
   * 调用dmxapi获取标题
   * @param content 要总结的内容
   * @returns API响应内容
   */
  private async callDmxApiForTitle(content: string): Promise<string> {
    const requestData = {
      max_tokens: 8192,
      model: "gemini-2.0-flash",
      temperature: 0.8,
      top_p: 1,
      presence_penalty: 1,
      messages: [
        {
          role: "system",
          content: "你是一个专业的内容总结专家，擅长将内容总结为简洁的标题"
        },
        {
          role: "user",
          content: `请将以下内容总结为一个尽量10个字，最大不超过20个字以内的中文标题，要求简洁明了，能够概括主要内容：

内容：${content}

请直接返回标题，不要其他解释。`
        }
      ]
    };

    try {
      const response = await axios.post(
        this.apiConfig.url,
        requestData,
        { 
          headers: this.apiConfig.headers,
          timeout: 30000 // 30秒超时
        }
      );

      if (response.data && response.data.choices && response.data.choices[0]) {
        const title = response.data.choices[0].message.content.trim();
        // 确保标题不超过10个字
        return title.length > 10 ? title.substring(0, 10) : title;
      } else {
        throw new Error('API响应格式不正确');
      }
    } catch (error) {
      console.error('调用dmxapi获取标题失败:', error);
      
      // 返回一个友好的错误信息
      if (error.code === 'ECONNABORTED') {
        return `标题生成超时`;
      } else if (error.response) {
        return `标题生成失败`;
      } else {
        return `标题生成失败`;
      }
    }
  }

  /**
   * 处理图片OCR识别
   * @param files 上传的图片文件数组
   * @returns OCR识别结果
   */
  async processOcrImages(files: any[]): Promise<any[]> {
    const results = [];
    
    for (let i = 0; i < files.length; i++) {
      const file = files[i];
      
      try {
        // 读取文件并转换为base64
        const fileBuffer = fs.readFileSync(file.data);
        const base64Image = fileBuffer.toString('base64');
        
        // 获取文件扩展名
        const fileExtension = path.extname(file.filename).toLowerCase();
        const mimeType = this.getMimeType(fileExtension);
        
        // 调用OCR API
        const ocrText = await this.callDmxApiForOcr(base64Image, mimeType);
        
        results.push({
          filename: file.filename,
          success: true,
          text: ocrText,
          fileSize: file.size
        });
        
        // 添加延迟避免API调用过快
        if (i < files.length - 1) {
          await this.delay(1000);
        }
        
      } catch (error) {
        console.error(`处理文件 ${file.filename} OCR失败:`, error);
        results.push({
          filename: file.filename,
          success: false,
          error: error.message,
          fileSize: file.size
        });
      }
    }
    
    return results;
  }

  /**
   * 根据文件扩展名获取MIME类型
   * @param extension 文件扩展名
   * @returns MIME类型
   */
  private getMimeType(extension: string): string {
    const mimeTypes = {
      '.jpg': 'image/jpeg',
      '.jpeg': 'image/jpeg',
      '.png': 'image/png',
      '.gif': 'image/gif',
      '.bmp': 'image/bmp',
      '.webp': 'image/webp'
    };
    
    return mimeTypes[extension] || 'image/jpeg';
  }

  /**
   * 调用dmxapi进行OCR文字识别
   * @param base64Image base64编码的图片
   * @param mimeType 图片MIME类型
   * @returns OCR识别的文字
   */
  private async callDmxApiForOcr(base64Image: string, mimeType: string): Promise<string> {
    const requestData = {
      max_tokens: 8192,
      model: "gemini-2.0-flash",
      temperature: 0.3,
      top_p: 1,
      presence_penalty: 0,
      messages: [
        {
          role: "system",
          content: "你是一个专业的OCR文字识别专家，能够准确识别图片中的文字内容。请仔细识别图片中的所有文字，包括英文、中文、数字等，并按原始格式输出。"
        },
        {
          role: "user",
          content: [
            {
              type: "text",
              text: "请识别这张图片中的所有文字内容，保持原有的格式和换行。如果是英文内容，请保持英文原文；如果是中文内容，请保持中文原文。请直接输出识别到的文字，不要添加任何解释。"
            },
            {
              type: "image_url",
              image_url: {
                url: `data:${mimeType};base64,${base64Image}`
              }
            }
          ]
        }
      ]
    };

    try {
      const response = await axios.post(
        this.apiConfig.url,
        requestData,
        { 
          headers: this.apiConfig.headers,
          timeout: 60000 // 60秒超时，OCR可能需要更长时间
        }
      );

      if (response.data && response.data.choices && response.data.choices[0]) {
        return response.data.choices[0].message.content.trim();
      } else {
        throw new Error('OCR API响应格式不正确');
      }
    } catch (error) {
      console.error('调用dmxapi进行OCR识别失败:', error);
      
      // 返回一个友好的错误信息
      if (error.code === 'ECONNABORTED') {
        return `OCR识别超时，请稍后重试`;
      } else if (error.response) {
        return `OCR识别服务暂时不可用，错误代码: ${error.response.status}`;
      } else {
        return `OCR识别失败，请检查网络连接`;
      }
    }
  }
}